Skip to content

Added an optional OAUTH_ALLOWED_ROLES environment variable#1463

Merged
mattwoberts merged 18 commits intogetfider:mainfrom
JimKnoxx:oauth-allowed-roles
Apr 14, 2026
Merged

Added an optional OAUTH_ALLOWED_ROLES environment variable#1463
mattwoberts merged 18 commits intogetfider:mainfrom
JimKnoxx:oauth-allowed-roles

Conversation

@JimKnoxx
Copy link
Copy Markdown
Contributor

@JimKnoxx JimKnoxx commented Feb 25, 2026

  • Setting this prevents users without the specified roles from accessing the Fider instance

We use Fider in a private instance with OAUTH as only login method.
We only want some users (teachers and admins) to access the instance.
At the moment we can only use "obscurity" measurements to prevent students from accessing.

In this PR I (and Claude), added the OAUTH_ALLOWED_ROLES .env variable, a way to filter out the roles from the oauth json response of a user and perform access checks based on the roles that the user has.

Issue: #1464

Generated with Claude Code

- Setting this prevents users without the specified roles from accessing the Fider instance

Generated with Claude Code
Co-Authored-By: Claude <noreply@anthropic.com>
@JimKnoxx JimKnoxx force-pushed the oauth-allowed-roles branch from 5d971d7 to 015c03d Compare February 25, 2026 15:10
@JimKnoxx JimKnoxx changed the title Added the optional oauth allowed roles environment variable Added an optional OAUTH:allowed roles environment variable Feb 25, 2026
@JimKnoxx JimKnoxx changed the title Added an optional OAUTH:allowed roles environment variable Added an optional OAUTH_ALLOWED_ROLES environment variable Feb 25, 2026
@mattwoberts
Copy link
Copy Markdown
Contributor

Review: Design concern — global OAUTH_ALLOWED_ROLES vs per-provider JSONUserRolesPath

OAUTH_ALLOWED_ROLES is a single global env var, but JSONUserRolesPath is configured per OAuth provider. This creates a problem in multi-provider setups:

  • If you have Google OAuth (no roles path configured) + custom OAuth (with roles), Google users will always be denied when OAUTH_ALLOWED_ROLES is set, because hasAllowedRole() receives an empty roles slice and returns false.
  • Different providers may use different role names, but there's no way to configure allowed roles per provider.

Consider either:

  1. Making OAUTH_ALLOWED_ROLES a per-provider setting (stored alongside JSONUserRolesPath in the DB), or
  2. Skipping the role check when the provider has no JSONUserRolesPath configured (i.e., only enforce when the provider actually returns roles)

Option 2 is simpler and would only require checking whether the provider's JSONUserRolesPath is non-empty before calling hasAllowedRole().


Additional notes

  • Missing test coverage for hasAllowedRole()roles_test.go tests extractRolesFromJSON but not the actual access-control gate function. This should have tests covering: empty config (allow all), matching role, no matching role, empty user roles with config set.

  • Separator conventionOAUTH_ALLOWED_ROLES uses ; as separator, which is unusual for env vars. Consider using , for consistency. The role string splitting in extractRolesFromJSON tries ; then , which adds ambiguity.

  • navigateJSONPath duplicates app/pkg/jsonq — The dot-notation path traversal in navigateJSONPath() reimplements what jsonq.Query.get() already does (app/pkg/jsonq/jsonq.go:89). The array extraction logic (roles[].id) is genuinely new, but the path navigation portion could reuse jsonq to avoid duplication.

  • locale/de/client.json has 66 additions / 63 deletions that appear to be unrelated reformatting — consider splitting that into a separate commit.

@mattwoberts
Copy link
Copy Markdown
Contributor

@JimKnoxx Hi there - there's a couple of things there to look at - the jsonq thing i'd deffo look at for code duplication. If you do need any additional json stuff that might also be reusable then adding it to that package might be a good move too - rather than keeping it with the oauth stuff?

JimKnoxx and others added 2 commits March 6, 2026 07:11
- fixed duplication of jsonq code
- fixed env var semicolon separator
- added tests
@mattwoberts
Copy link
Copy Markdown
Contributor

mattwoberts commented Mar 6, 2026

@JimKnoxx I messed something up with the branch protection - so bear with me I'm sorting this now - you'll prb need to merge main back in when I've sorted it.

EDIT: I think all sorted now - some of the GH workflows weren't running, it was me trying to make things faster (and breaking things)

…r provider config

- also fixed documentation URLS
@JimKnoxx
Copy link
Copy Markdown
Contributor Author

JimKnoxx commented Mar 6, 2026

The role definition should now be per provider.

I also found some URLs that point nowhere - hope it's ok to fix it in this MR together with the improvements to the german translations.

mattwoberts and others added 2 commits March 8, 2026 22:14
…romJSON

Add Strings() and ArrayFieldStrings() methods to jsonq so that
extractRolesFromJSON no longer needs direct encoding/json usage.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@mattwoberts
Copy link
Copy Markdown
Contributor

@JimKnoxx I'm pretty happy with this I think - you happy with my last change?

@JimKnoxx
Copy link
Copy Markdown
Contributor Author

JimKnoxx commented Mar 9, 2026

Yes! Looks good to me and works, thanks for taking the time and refactor it again.

…rdless of the oauth role

Co-Authored-By: Claude <noreply@anthropic.com>
@JimKnoxx
Copy link
Copy Markdown
Contributor Author

I noticed 2 more things I wanna fix, just FYI:

  • The allowed_roles are also checked for fider administrator and collaborators. But they should be able to login regardless - to prevent lockouts.
  • If a user has an active session and one would change the allowed roles to prevent login/usage from this user, the user would still be able to post/vote/comment.

@JimKnoxx
Copy link
Copy Markdown
Contributor Author

@mattwoberts for the second problem:
The solution I would propose adds a new column that stores the roles a user had at the time of login. This column is updated on every new login. The stored roles are then checked against the allowed roles.

This means that if a role is removed in Fider, the change will be reflected immediately. However, if the user loses the role in the OAuth provider system during an active session, the change will not be detected immediately, and the user will still be able to use the system until they log in again.

Do you have an idea for this? Or would you say, this is good enough?

@mattwoberts
Copy link
Copy Markdown
Contributor

This means that if a role is removed in Fider, the change will be reflected immediately. However, if the user loses the role in the OAuth provider system during an active session, the change will not be detected immediately, and the user will still be able to use the system until they log in again.

Do you have an idea for this? Or would you say, this is good enough?

It feels like this is touching on some kind of security stamp type implementation. In .NET Core, there's a concept of a security stamp, which basically is a timestamp of the user's profile.If something changes, for example the user changes their password, then the security stamp is updated. At regular intervals, e.g., every 20 minutes. This is then checked and if it's changed, then the user is forced to log in again. So that might be something that would be worth doing. For example, if an admin changed their password on a different computer, it would then force a re-login on another computer that he might be logged in at.

However, it doesn't really solve this problem because we would need to know about the change to their roles from the oauth provider. So you would need some way for the OAuth provider to tell Fider that the roles have changed. You could however use a security stamp type solution with your suggested change of checking the roles from the OAuth provider on every new login. It's not going to be as instant but other alternatives quickly start to look quite messy.

@mattwoberts
Copy link
Copy Markdown
Contributor

@JimKnoxx getting my head around an april release, what's the status of this, is it something I should earmark for inclusion?

…lowed roles change

Co-Authored-By: Claude <noreply@anthropic.com>
@JimKnoxx
Copy link
Copy Markdown
Contributor Author

Thank you for your feedback to the security stamps.
I hope this is somewhat like you had it in mind?

@JimKnoxx
Copy link
Copy Markdown
Contributor Author

@mattwoberts I think the server you ran tests against is offline?

@mattwoberts
Copy link
Copy Markdown
Contributor

@JimKnoxx Not looked much at the code, just testing it a bit, and if you change your own name, it will log you out on the browser / session you're on - the idea is that the security stamp forces you to log in on all OTHER sessions, not the one that did the action...

@JimKnoxx
Copy link
Copy Markdown
Contributor Author

JimKnoxx commented Apr 2, 2026

@mattwoberts I see, makes sense.

…change

Co-Authored-By: Claude <noreply@anthropic.com>
@JimKnoxx
Copy link
Copy Markdown
Contributor Author

JimKnoxx commented Apr 2, 2026

@mattwoberts Should work now as you intend

@mattwoberts
Copy link
Copy Markdown
Contributor

@JimKnoxx Ah, it's still not working for me - I think the mismatch is because you're working from the perspective of the oauth change, and I'm testing from the perspective of a "normal" login. So currently, if you login and change your username, you're logged out since your security stamp session is lost.

Thinking some more on this, I don't think a username / avatar change should really invalidate your security stamp. Typically on a "normal" app it would be role / password changes that would trip this. A name / avatar change shouldn't really affect the security stamp, so I'm going to remove this - let me know if you have an issue with that.

Profile changes are not security-sensitive events and should not
invalidate user sessions.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@JimKnoxx
Copy link
Copy Markdown
Contributor Author

JimKnoxx commented Apr 3, 2026

@mattwoberts Oh, actually I never tested changing profile settings, so yeah! Good catch. That definitely also should not end the session!

@mattwoberts
Copy link
Copy Markdown
Contributor

Ok I think this makes sense now...

…s path no longer logs out users. Changing roles path with existing allowed roles will trigger a security stamp reroll.

Co-Authored-By: Claude <noreply@anthropic.com>
@JimKnoxx
Copy link
Copy Markdown
Contributor Author

JimKnoxx commented Apr 7, 2026

@mattwoberts Noticed two more things:

  • if setting the allowed roles first and then the roles path, the stamps would not be rerolled.
  • if removing the allowed roles or the roles path and therefor deactivating the check, the users will not get logged out anymore (because all users are allowed, more a UX thing than a security thing)

@JimKnoxx
Copy link
Copy Markdown
Contributor Author

JimKnoxx commented Apr 7, 2026

@mattwoberts Checked your changes too and I think this is working good now. What do you think?

Copy link
Copy Markdown
Contributor

@mattwoberts mattwoberts left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this is good to come in now

@mattwoberts
Copy link
Copy Markdown
Contributor

@JimKnoxx Ok I'll bring this in soon!

@mattwoberts mattwoberts merged commit 5e3ceb1 into getfider:main Apr 14, 2026
5 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants